home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / ov143b.zip / OVWIN.C < prev    next >
C/C++ Source or Header  |  1993-01-04  |  34KB  |  958 lines

  1. /*  037  23-May-87  ovwin.c
  2.  
  3.         Copyright (c) 1987 by Blue Sky Software.  All rights reserved.
  4. */
  5.  
  6. #include <setjmp.h>
  7. #include <dos.h>
  8. #include "ov.h"
  9. #include "overr.h"
  10. #include "direct.h"
  11. #include "strmem.h"
  12.  
  13. #define V_bar (0xba)
  14. #define H_bar (0xcd)
  15.  
  16. int diridx = 0;                        /* # dir names when showall */
  17. char **dirlst = NULL;                  /* ptr to dir name ptrs when showall */
  18.  
  19. static int win_update;                         /* NZ if refresh_screen update */
  20. static unsigned char inwin = 0;                /* # active info windows */
  21. static unsigned char numwin = 1;               /* # active windows */
  22. static WINDOW *curwin = NULL, *winlis = NULL, *winp;
  23.  
  24. static char *tdir;                             /* target dir */
  25. static char *tname;                            /* target name */
  26. static FILE_ENT holdf;                         /* save file_ent */
  27.  
  28. static char *nomem = "Insufficient memory for another window, no window created!";
  29. static char *noaccess = "Unable to access specified directory: ";
  30.  
  31. extern WINDOW cw;
  32. extern int winupdate;
  33. extern FILE_ENT files[];
  34. extern unsigned dataseg;
  35. extern jmp_buf back_to_main;
  36. extern unsigned char anyshowall;
  37.  
  38. char far *malloc_f();
  39. int ALTCALL scanwindows(), ALTCALL win_switch();
  40. int addfile_ent(), delfile_ent(), refresh_window();
  41. char *strrchr(), *strchr(), *parsepath(), *findir();
  42. int ALTCALL wincpy(WINDOW *, WINDOW *), ALTCALL disp_empty_msg(int);
  43. int ALTCALL savefiles(char far *, int), ALTCALL restorefiles(char far *, int);
  44.  
  45. /******************************************************************************
  46.  **                         W I N _ O P E N                                  **
  47.  *****************************************************************************/
  48.  
  49. win_open() {           /* open another file name display window */
  50.  
  51.    register WINDOW *wp;
  52.  
  53.    /* make sure the current window is large enough to split */
  54.  
  55.    if (cw.wrows < 6)
  56.       show_error(0,WIN_2_SMALL,1,"Current window is too small to open another");
  57.  
  58.    /* allocate memory for the new window structure */
  59.  
  60.    if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL)
  61.       show_error(0,NO_MEM,1,nomem);
  62.  
  63.    wincpy(wp,&cw);             /* initialize new window via current window */
  64.  
  65.    /* allocate memory to store files[] data */
  66.  
  67.    if ((wp->save_files = malloc_f(MAX_FILES * sizeof(FILE_ENT))) == NULL) {
  68.       free((char *)wp);
  69.       show_error(0,NO_MEM,1,nomem);
  70.    }
  71.  
  72.    /*  if there is only one window open so far, create the window structure
  73.        and files[] save area to store the current window stuff */
  74.  
  75.    if (numwin == 1) {
  76.       curwin = (WINDOW *) malloc(sizeof(WINDOW));
  77.       cw.save_files = malloc_f(MAX_FILES * sizeof(FILE_ENT));
  78.       if (curwin == NULL || cw.save_files == NULL) {
  79.          free((char *)wp);
  80.          if (curwin) {
  81.             free((char *)curwin);
  82.             curwin = NULL;
  83.          }
  84.          show_error(0,NO_MEM,1,nomem);
  85.       }
  86.       cw.prev = cw.next = winlis = curwin;
  87.    }
  88.  
  89.    savefiles(cw.save_files,cw.nfiles); /* save current window's files[] data */
  90.  
  91.    /* link the new window just after the current window */
  92.  
  93.    wincpy(curwin,&cw);
  94.    wp->next = curwin->next;
  95.    wp->prev = curwin;
  96.    wp->prev->next = wp;
  97.    wp->next->prev = wp;
  98.    wincpy(&cw,curwin);
  99.  
  100.    /* adjust the current window and new window display sizes */
  101.  
  102.    wp->wrows = cw.wrows / 2;           /* new is at most 1/2 of current */
  103.    cw.wrows = cw.wrows - wp->wrows;    /* current keeps whats left */
  104.    wp->fwrow = cw.fwrow + cw.wrows;    /* new start at end of current */
  105.    cw.ndrows -= wp->wrows;             /* all new rows came from name disp */
  106.    wp->fnrow = wp->fwrow + 1;          /* one overhead row for dir name */
  107.    wp->ndrows = wp->wrows - 1;
  108.  
  109.    /* adjust the top window if it was the only one and it didn't already
  110.       have a header line */
  111.  
  112.    if (numwin == 1 && !cw.showall) {
  113.       cw.fnrow++;                         /* need a line to display window */
  114.       cw.ndrows--;                        /*   directory line */
  115.       insert_line(cw.fwrow+1,cw.wrows-1); /* scroll file info down a line */
  116.       disp_dirname();                     /* disp the dir name */
  117.    }
  118.  
  119.    /* adjust old window if current item is no longer visible and turn off
  120.       the file pointer in the old window */
  121.  
  122.    if (!on_screen(cw.curidx)) {        /* adjust/redisplay window */
  123.  
  124.       adjust_window();                 /*   if current item no longer */
  125.       update_window(0);                /*   displayed */
  126.  
  127.    } else              /* not redisplaying window, turn off highlighted ptr */
  128.  
  129.       if (cw.nfiles)                      /* turn off file ptr in old window */
  130.          fp_off(cw.curidx);
  131.       else                                /* or de-highlight empty dir msg */
  132.          disp_empty_msg(0);
  133.  
  134.    /* make the new window the current one */
  135.  
  136.    wincpy(curwin,&cw);                 /* save the old current one */
  137.    wincpy(&cw,wp);                     /* new one becomes current */
  138.    curwin = wp;                        /* remember who it is */
  139.  
  140.    numwin++;                           /* one more window than there was */
  141.  
  142.    if (cw.info_display)                /* if info display is active, there */
  143.       infocnt(1);                      /*   is now 1 more info window active */
  144.  
  145.    /* only one window can be in showall mode */
  146.  
  147.    if (cw.showall) {                   /* did the old window have showall? */
  148.       cw.showall = 0;                  /* yes, turn off on this one */
  149.       getfiles();                      /* reread current dir only */
  150.       update_header();                 /* display current dir header info */
  151.    }
  152.  
  153.    /* display the file data in the new window */
  154.  
  155.    adjust_window();
  156.    update_window(1);
  157.  
  158. }
  159.  
  160.  
  161. /******************************************************************************
  162.                             W I N _ C L O S E
  163.  *****************************************************************************/
  164.  
  165. win_close() {          /* close the current window */
  166.  
  167.    int fwrowadj;
  168.    register WINDOW *wp;
  169.  
  170.    if (numwin == 1)            /* nothing to do if only one window */
  171.       return;
  172.  
  173.    /* determine the window adjustment fudge factor, 1 extra line is available
  174.       if only one window will remain and that window is not showall */
  175.  
  176.    fwrowadj = (numwin == 2 && (!anyshowall || cw.showall)) ? 0 : 1;
  177.  
  178.    /* adjust the next or prior window to take up the closing windows space
  179.       on the screen.  Always pick the next window unless current is the
  180.       last one displyed */
  181.  
  182.    if ((wp = cw.next) != winlis) {             /* next = winlis if last */
  183.  
  184.       wp->fwrow = cw.fwrow;                    /* adj nxt to take over */
  185.  
  186.    } else              /* closing last window on screen */
  187.  
  188.       wp = cw.prev;                            /* prev is current to be */
  189.  
  190.    wp->wrows += cw.wrows;              /* it has this many more rows */
  191.    wp->fnrow = wp->fwrow + fwrowadj;   /*   name display rows */
  192.    wp->ndrows = wp->wrows - fwrowadj;
  193.  
  194.    cw.next->prev = cw.prev;            /* delink the current (closing) */
  195.    cw.prev->next = cw.next;            /* windows block from window list */
  196.  
  197.    if (curwin == winlis)               /* keep track of new top window if */
  198.       winlis = wp;                     /* old top is being closed */
  199.  
  200.    if (cw.showall)                     /* turn off showall mode if this */
  201.       showoff();                       /*   window had it on */
  202.  
  203.    if (cw.info_display)                /* one less info window if this wind */
  204.       infocnt(-1);                     /*   had info display active */
  205.  
  206.    free_f(cw.save_files);              /* free the cur win's  files[] area */
  207.    free((char *)curwin);               /* free the cur/old win's block */
  208.  
  209.    /* make the next (or prior) window current, restore its files */
  210.  
  211.    wincpy(&cw,curwin = wp);
  212.    restorefiles(cw.save_files,cw.nfiles);
  213.  
  214.    numwin--;                           /* one less window now */
  215.  
  216.    /* when there is only one window, don't keep the block and files[]
  217.       save area overhead */
  218.  
  219.    if (numwin == 1) {
  220.       free((char *)curwin);
  221.       free_f(cw.save_files);
  222.       curwin = winlis = NULL;
  223.       cw.save_files = (char far *) NULL;
  224.    }
  225.  
  226.    update_header();            /* make volume, dir, file, tag info correct */
  227.  
  228.    adjust_window();            /* adjust the display */
  229.    update_window(1);
  230.  
  231.    /* switch to the window's directory */
  232.  
  233.    if (change_dir(cw.dirbuf) != 0)
  234.       show_error(SHOW_DOS,0,1,noaccess);
  235. }
  236.  
  237.  
  238. /******************************************************************************
  239.                             W I N _ E X P A N D
  240.  *****************************************************************************/
  241.  
  242. win_expand() {         /* expand current window to full screen */
  243.  
  244.    int i;
  245.    register WINDOW *wp, *np;
  246.  
  247.    if (numwin == 1)            /* nothing to do if only one window */
  248.       return;
  249.  
  250.    /* there will only be one window left, free up all memory blocks */
  251.  
  252.    for (i == numwin, wp = winlis; i; i--) {
  253.       np = wp->next;
  254.       free_f(wp->save_files);
  255.       free((char *)wp);
  256.       wp = np;
  257.    }
  258.  
  259.    numwin = 1;                 /* set counters/pointer to 1 window status */
  260.    curwin = winlis = NULL;
  261.  
  262.    if (anyshowall && !cw.showall)      /* turn off showall mode if it was */
  263.       showoff();                       /*   active in another window */
  264.  
  265.    infocnt(cw.info_display ? -(inwin-1) : -inwin); /* at most 1 info win left */
  266.  
  267.    /* adjust to full screen */
  268.  
  269.    cw.fwrow = cw.fnrow = FIRST_NROW + cw.info_display;
  270.    cw.wrows = cw.ndrows = NAME_ROWS - cw.info_display;
  271.  
  272.    if (cw.showall) {           /* showall always has a header */
  273.       cw.fnrow++;
  274.       cw.ndrows--;
  275.    }
  276.  
  277.    adjust_window();            /* redisplay the window with new size */
  278.    update_window(1);
  279.  
  280. }
  281.  
  282.  
  283. /******************************************************************************
  284.  **                         W I N _ N E X T                                  **
  285.  *****************************************************************************/
  286.  
  287. win_next() {           /* switch to the next window */
  288.  
  289.    if (numwin == 1)            /* nothing to do if only one window */
  290.       return;
  291.  
  292.    win_switch(curwin->next);   /* switch to next window */
  293. }
  294.  
  295.  
  296. /******************************************************************************
  297.                             W I N _ P R E V
  298.  *****************************************************************************/
  299.  
  300. win_prev() {           /* switch to the previous window */
  301.  
  302.    if (numwin == 1)            /* nothing to do if only one window */
  303.       return;
  304.  
  305.    win_switch(curwin->prev);   /* switch to previous window */
  306. }
  307.  
  308.  
  309. /******************************************************************************
  310.                             W I N _ S W I T C H
  311.  *****************************************************************************/
  312.  
  313. static int ALTCALL
  314. win_switch(newp)       /* switch to a new window */
  315. register WINDOW *newp;
  316. {
  317.    savefiles(cw.save_files,cw.nfiles); /* save current window's files[] data */
  318.  
  319.    if (cw.nfiles)                      /* deselect current item in widow */
  320.       fp_off(cw.curidx);
  321.    else                                /* or de-highlight empty dir msg */
  322.       disp_empty_msg(0);
  323.  
  324.    wincpy(curwin,&cw);                 /* switch to new window */
  325.    wincpy(&cw,curwin = newp);
  326.  
  327.    restorefiles(cw.save_files,cw.nfiles); /* get new windows files[] entries */
  328.  
  329.    if (cw.nfiles)                      /* select current item in new window */
  330.       fp_on(cw.curidx);
  331.    else                                /* or highlight empty dir msg */
  332.       disp_empty_msg(1);
  333.  
  334.    if (change_dir(cw.dirbuf) != 0)     /* switch to the window's directory */
  335.       show_error(SHOW_DOS,0,1,noaccess);
  336.  
  337.    update_header();               /* make volume, dir, file, tag info correct */
  338. }
  339.  
  340.  
  341. /*****************************************************************************
  342.                           A D D 2 W I N D O W S
  343.  *****************************************************************************/
  344.  
  345. add2windows(todir,tofn,fp)     /* add file to any windows showing dest dir */
  346. FILE_ENT *fp;
  347. char *todir, *tofn;
  348. {
  349.    tdir = Strdup(todir);       /* save dir and fn in var's for addfile_ent */
  350.    tname = Strdup(tofn);
  351.  
  352.    holdf = *fp;                /* save file_ent 'cause files[] is changed */
  353.    holdf.flags &= ~TAGGED;     /* we don't want the tagged flag */
  354.  
  355.    scanwindows(addfile_ent);   /* add the file_ent to all matching windows */
  356.  
  357.    free(tdir);                 /* local strings alloc'd because callers tend */
  358.    free(tname);                /* to use strings in files[] which is swapped */
  359. }
  360.  
  361.  
  362. /*****************************************************************************
  363.                           D E L F R O M W I N S
  364.  *****************************************************************************/
  365.  
  366. delfromwins(fromdir,fromfn)  /* delete file from all windows showing dest dir */
  367. char *fromdir, *fromfn;
  368. {
  369.  
  370.    tdir = Strdup(fromdir);     /* save target dir and name in var's */
  371.    tname = Strdup(fromfn);     /*   for delfile_ent */
  372.  
  373.    scanwindows(delfile_ent);   /* delete the file_ent from all windows */
  374.  
  375.    free(tdir);                 /* local strings alloc'd because callers tend */
  376.    free(tname);                /* to use strings in files[] which is swapped */
  377. }
  378.  
  379.  
  380. /****************************************************************************
  381.                           A D D F I L E _ E N T
  382.  ****************************************************************************/
  383.  
  384. static int
  385. addfile_ent() {        /* add a FILE_ENT to target windows */
  386.  
  387.    register int i;
  388.    register FILE_ENT *tfp;
  389.  
  390.    /* if the current window displays the target dir or the target drive
  391.       in showall mode, add the file ent to it */
  392.  
  393.    if (stricmp(cw.dirbuf,tdir) == 0 || (cw.showall && *cw.dirbuf == *tdir)) {
  394.  
  395.       /* don't add the file if it doesn't match the selection criteria */
  396.  
  397.       if ((cw.selatrs & holdf.flags) != holdf.flags ||
  398.           (*cw.mask && (cw.maskcmp != match_name(holdf.name,cw.mask))))
  399.          return;
  400.  
  401.       if (numwin > 1)                       /* make sure files[] is ok */
  402.          restorefiles(cw.save_files,cw.nfiles);
  403.  
  404.       /* see if there is an existing file by that name in the target dir */
  405.  
  406.       for (i = 0, tfp = files; i < cw.nfiles; i++, tfp++)
  407.           if (stricmp(tname,tfp->name) == 0 && stricmp(tdir,tfp->dirp) == 0)
  408.              break;
  409.  
  410.       if (i < cw.nfiles) {          /* back out info for an existing  */
  411.          delent(tfp);               /* file by the same name          */
  412.          packfiles();               /* pack files[] now, not later    */
  413.          if (i < cw.curidx)         /* adjust current file pointer if */
  414.             cw.curidx--;            /* deleted file before current    */
  415.       }
  416.  
  417.       /* modify holding file entry to its final form */
  418.  
  419.       strncpy(holdf.name,tname,sizeof(holdf.name));        /* file name */
  420.       holdf.dirp = cw.showall ? findir(tdir) : cw.dirbuf;  /* file's dir */
  421.       holdf.index = cw.nfiles+1;                           /* a guess */
  422.  
  423.       /* add file to files[] if there is room */
  424.  
  425.       if (cw.nfiles < MAX_FILES) {
  426.  
  427.          /* since the files may be sorted by something other than name (say
  428.             date for example) we need to scan files[] again to find where to
  429.             insert the new entry - I used to just sort files[] again but qsort
  430.             is way to slow when files[] is already almost sorted */
  431.  
  432.          for (i = cw.nfiles, tfp = files; i; i--, tfp++)
  433.              if ((*cw.sortfunc)(&holdf,tfp) < 0)
  434.                 break;
  435.  
  436.          /* i > 0 if entry needs to be inserted, i = 0 if at end */
  437.  
  438.          if (i)
  439.             memcpy((char *)(tfp+1),(char *)tfp,i*sizeof(FILE_ENT));
  440.  
  441.          *tfp = holdf;                 /* finally, add entry */
  442.          cw.nfiles++;                  /* there is one more file now */
  443.          cw.num_files++;
  444.          cw.files_size += tfp->size;   /* taking this much more space */
  445.          cw.updated = W_DISP;          /* win needs redisplay (not packing) */
  446.          winupdate++;                  /* some window needs redisplay */
  447.  
  448.          if (tfp < &files[cw.curidx])  /* bump current file pointer if added */
  449.             cw.curidx++;               /* file is before current file        */
  450.  
  451.          if (numwin > 1)
  452.             savefiles(cw.save_files,cw.nfiles);
  453.       }
  454.    }
  455. }
  456.  
  457.  
  458. /****************************************************************************
  459.                           D E L F I L E _ E N T
  460.  ****************************************************************************/
  461.  
  462. static int
  463. delfile_ent() {        /* delete a FILE_ENT from target windows */
  464.  
  465.    register int i;
  466.    register FILE_ENT *tfp;
  467.  
  468.    /* if the current window displays the target dir or the target drive
  469.       in showall mode, delete the file ent */
  470.  
  471.    if (stricmp(cw.dirbuf,tdir) == 0 || (cw.showall && *cw.dirbuf == *tdir)) {
  472.  
  473.       if (numwin > 1)                       /* make sure files[] is ok */
  474.          restorefiles(cw.save_files,cw.nfiles);
  475.  
  476.       /* see if there is an existing file by that name in the target dir */
  477.  
  478.       for (i = 0, tfp = files; i < cw.nfiles; i++, tfp++)
  479.           if (stricmp(tname,tfp->name) == 0 && stricmp(tdir,tfp->dirp) == 0)
  480.              break;
  481.  
  482.       if (i < cw.nfiles) {          /* back out info for an existing */
  483.          delent(tfp);               /* file by the same name         */
  484.          winupdate++;               /* window needs redisplay        */
  485.          cw.updated |= W_PACK;      /* files[] needs to be packed    */
  486.          if (i < cw.curidx)         /* move file pointer if deleted  */
  487.             cw.curidx--;            /* file is before current        */
  488.          if (numwin > 1)
  489.             savefiles(cw.save_files,cw.nfiles);
  490.       }
  491.    }
  492. }
  493.  
  494.  
  495. /*****************************************************************************
  496.                                 D E L E N T
  497.  *****************************************************************************/
  498.  
  499. delent(fp)             /* remove an entry from files[] */
  500. register FILE_ENT *fp;
  501. {
  502.    /* Note: this routine changes cw.num_files, but it doesn't change
  503.       cw.nfiles - this is because the routine packfiles which should
  504.       be called shortly needs the old value of cw.nfiles */
  505.  
  506.    cw.num_files--;                     /* one fewer file */
  507.    cw.files_size -= fp->size;          /* that much space not used */
  508.    if (fp->flags & TAGGED) {           /* was file tagged? */
  509.       cw.num_tagged--;                 /* one less tagged file */
  510.       cw.tag_size -= fp->size;         /* this space not tagged now */
  511.    }
  512.    *fp->name = '\0';                   /* mark this entry as deleted */
  513. }
  514.  
  515.  
  516. /****************************************************************************
  517.                           S C A N W I N D O W S
  518.  ****************************************************************************/
  519.  
  520. static int ALTCALL
  521. scanwindows(func)      /* scan windows, call func for each one */
  522. int (*func)();
  523. {
  524.    int i;
  525.    register WINDOW *wp;
  526.  
  527.    /* if there is a list of windows, start with the 1st; switch if not there */
  528.  
  529.    if (numwin > 1) {
  530.       wincpy(curwin,&cw);                      /* save current window if > 1 */
  531.       savefiles(cw.save_files,cw.nfiles);
  532.       if (curwin != winlis) {                  /* temp switch to top window */
  533.          wincpy(&cw,winlis);
  534.       }
  535.    }
  536.  
  537.    /* Note: only the files for the original window are saved and restored,
  538.       callers func should restore/savefiles if it needs to */
  539.  
  540.    for (i = numwin, wp = winlis; i; i--) {     /* check each file window */
  541.  
  542.       winp = wp;               /* let func know which window it is */
  543.  
  544.       (*func)();               /* invoke callers func with this window */
  545.  
  546.       if (numwin > 1) {        /* advance to next window if there is one */
  547.          wincpy(wp,&cw);
  548.          wincpy(&cw,wp = cw.next);
  549.       }
  550.    }
  551.  
  552.    if (numwin > 1) {           /* restore the current window if > 1 */
  553.       wincpy(&cw,curwin);
  554.       restorefiles(cw.save_files,cw.nfiles);
  555.    }
  556. }
  557.  
  558.  
  559. /******************************************************************************
  560.  **                             R E N E W                                    **
  561.  *****************************************************************************/
  562.  
  563. renew() {              /* renew the file display */
  564.  
  565.    getcwd(cw.dirbuf,MAX_PATHLEN);        /* reinit drive/dir info incase */
  566.    initdrive(*cw.dirbuf);                /*   it changed somehow */
  567.  
  568.    getfiles();                         /* reread the directory */
  569.    setup_file_scr();                   /* display the static screen image */
  570.    update_header();                    /* update header info */
  571.    refresh_screen(0);                  /* redisplay all file data */
  572. }
  573.  
  574.  
  575. /******************************************************************************
  576.                         R E N E W _ W I N D O W
  577.  *****************************************************************************/
  578.  
  579. renew_window() {       /* renew the current window display */
  580.  
  581.    getfiles();                         /* reload the files[] structure */
  582.    adjust_window();                    /* resize window data */
  583.    update_header();                    /* update the header  */
  584.    update_window(1);                   /* and the window data */
  585. }
  586.  
  587.  
  588. /******************************************************************************
  589.                           R E F R E S H _ S C R E E N
  590.  *****************************************************************************/
  591.  
  592. refresh_screen(wup)    /* (re)initialize the total file data display */
  593. int wup;
  594. {
  595.    win_update = wup;          /* save wup in static for refresh_window */
  596.  
  597.    if (inwin && wup == 0)     /* display the info header if needed */
  598.       infohead();
  599.  
  600.    scanwindows(refresh_window);        /* redisplay each window */
  601. }
  602.  
  603. /*****************************************************************************
  604.                         R E F R E S H _ W I N D O W
  605.  *****************************************************************************/
  606.  
  607. static int
  608. refresh_window() {     /* refresh one window - called by scanwindows */
  609.  
  610.    if (numwin > 1)
  611.       restorefiles(cw.save_files,cw.nfiles);
  612.  
  613.    if (win_update && cw.updated) {     /* is this a window update call? */
  614.       if (cw.updated & W_PACK)
  615.          packfiles();
  616.       if (numwin > 1)
  617.          savefiles(cw.save_files,cw.nfiles);
  618.    }
  619.  
  620.    /* redisplay this window if not a win_update call or win_update call and
  621.       this window has been modified */
  622.  
  623.    if (!win_update || cw.updated) {
  624.       adjust_window();                 /* calculate display parameters */
  625.       update_window(winp == curwin);   /* update display window */
  626.       cw.updated = 0;                  /* doesn't need to be updated again */
  627.    }
  628. }
  629.  
  630.  
  631. /******************************************************************************
  632.                     U P D A T E _ V O L _ S T A T S
  633.  ******************************************************************************/
  634.  
  635. update_vol_stats() {   /* get and display volume statistics */
  636.  
  637.    getvolsiz(*cw.dirbuf,&cw.drivep->vol_size,&cw.drivep->vol_free,
  638.              &cw.drivep->clustersiz);
  639.    disp_vol_stats();
  640. }
  641.  
  642.  
  643. /******************************************************************************
  644.                         U P D A T E _ H E A D E R
  645.  ******************************************************************************/
  646.  
  647. update_header() {      /* update display header */
  648.  
  649.    gotorc(VOL_ROW,1);                  /* make sure volume, directory, */
  650.    out_str(cw.drivep->volbuf,11,' ');  /* file, tagged info is correct */
  651.  
  652.    if (!cw.showall) {                  /* display the current dir name */
  653.       gotorc(VOL_ROW,PATH_COL+1);      /*   but if showall is in effect */
  654.       out_str(cw.dirbuf,65,' ');       /*   its done somewhere else */
  655.    }
  656.  
  657.    disp_vol_stats();
  658.    disp_file_stats();
  659.  
  660.    gotorc(MASK_ROW,MASK_COL-1);        /* display the selection mask */
  661.    disp_char(cw.maskcmp ? ' ' : '~');
  662.    out_str(cw.mask,MASK_LEN,' ');
  663.  
  664.    gotorc(MASK_ROW+1,MASK_COL-1);      /* display the selection attributes */
  665.    disp_attrib(cw.selatrs);
  666.    disp_str(cw.selatrs & DIR ? " D" : " .");
  667. }
  668.  
  669.  
  670. /******************************************************************************
  671.                         U P D A T E _ W I N D O W
  672.  *****************************************************************************/
  673.  
  674. int ALTCALL
  675. update_window(fptr)    /* display a window full of file info */
  676. int fptr;
  677. {
  678.    int col;
  679.    register int i, m;
  680.  
  681.    if (numwin > 1 || cw.showall)       /* display window header if > 1 */
  682.       disp_dirname();                  /*   window or showall mode */
  683.  
  684.    /* display a window of file names */
  685.  
  686.    for (i = 0; i + cw.fnrow < cw.fnrow + cw.ndrows; i++) {
  687.  
  688.       gotorc(i+cw.fnrow,0);
  689.  
  690.       if (i < cw.nrows) {
  691.          for (col = 0, m = cw.nbase + i; m < cw.nfiles; col++, m += cw.nrows)
  692.             disp_file(&files[m],(m == cw.curidx && fptr));
  693.  
  694.          if (col < cw.ncols)   /* try to only clear on rows where less */
  695.             clr_eol();         /* than ncols are displayed */
  696.       } else
  697.          clr_eol();
  698.    }
  699.  
  700.    /* display files dir path if showall mode */
  701.  
  702.    if (fptr && cw.showall && cw.curidx < cw.nfiles)
  703.       disp_path(cw.curidx);
  704.  
  705.    if (cw.nfiles == 0)         /* display a msg if no files in dir */
  706.       disp_empty_msg(fptr);
  707. }
  708.  
  709.  
  710. /******************************************************************************
  711.                         A D J U S T _ W I N D O W
  712.  *****************************************************************************/
  713.  
  714. int ALTCALL
  715. adjust_window() {
  716.  
  717.    /* for MS DOS, assume the max length file name is 13.  8 for the primary
  718.       name, 1 for '.', 3 for the extension, and 1 for '\' if its a directory */
  719.  
  720.    cw.maxlen = MAX_NAMELEN + 1;
  721.  
  722.    /* everything depends on # files in directory */
  723.  
  724.    if (cw.nfiles == 0)                 /* unusual, but dir may be empty */
  725.       cw.nrows = cw.ncols = 1;
  726.    else {                              /* are files, calc logical rows, cols */
  727.       cw.ncols = (cw.info_display) ? 1 : 5;
  728.       cw.nrows = (cw.nfiles+(cw.ncols-1)) / cw.ncols;
  729.    }
  730.  
  731.    cw.colsiz = SCREEN_COLS / cw.ncols;         /* width of each column */
  732.  
  733.    /* update current logical idx */
  734.  
  735.    if (cw.curidx >= cw.nfiles)
  736.       cw.curidx = cw.nfiles ? cw.nfiles - 1 : 0;
  737.  
  738.    /* make sure nbase is setup such that the current file is displayed */
  739.  
  740.    if (cw.nfiles <= cw.ndrows * cw.ncols) /* if file entries will fit on */
  741.       cw.nbase = 0;                       /*   1 screen, start at 1st */
  742.    else {
  743.       cw.nbase = idx2lr(cw.curidx) - cw.ndrows / 2;  /* try to center curidx */
  744.       if (cw.nbase > 0 && cw.nbase + cw.ndrows > cw.nrows) /* no blank rows  */
  745.          cw.nbase = cw.nrows - cw.ndrows;                  /* if possible    */
  746.       if (cw.nbase < 0)                              /* might overshoot */
  747.          cw.nbase = 0;
  748.    }
  749.  
  750. }
  751.  
  752.  
  753. /******************************************************************************
  754.                              I N F O C N T
  755.  *****************************************************************************/
  756.  
  757. infocnt(chg)           /* display/remove info header when required */
  758. int chg;
  759. {
  760.    int cur_isnt_top;
  761.  
  762.    inwin += chg;                       /* more or less info windows */
  763.  
  764.    cur_isnt_top = (numwin > 1 && curwin != winlis);
  765.  
  766.    /* if the count of info windows just went to 0, or it just went from 0 to 1,
  767.       we need to add or remove the info display header.  The top display
  768.       window losses or gains a row when this happens */
  769.  
  770.    if ((inwin == 0 && chg) || (inwin == 1 && chg > 0)) {
  771.  
  772.       /* do a temp switch to the top window if not already there */
  773.  
  774.       if (cur_isnt_top) {
  775.          wincpy(curwin,&cw);
  776.          savefiles(cw.save_files,cw.nfiles);
  777.          wincpy(&cw,winlis);
  778.          restorefiles(cw.save_files,cw.nfiles);
  779.       }
  780.  
  781.       /* now add or remove a row from the window */
  782.  
  783.       if (inwin) {                     /* remove a line, display header */
  784.          cw.fwrow++;  cw.fnrow++;
  785.          cw.wrows--;  cw.ndrows--;
  786.          infohead();
  787.       } else {                         /* add a line, remove header */
  788.          cw.fwrow--;  cw.fnrow--;
  789.          cw.wrows++;  cw.ndrows++;
  790.       }
  791.  
  792.       /* now update the top window display, but don't bother if the current
  793.          window is the top window - it will be updated by caller */
  794.  
  795.       if (cur_isnt_top) {
  796.          adjust_window();      /* calculate #rows, columns, etc to display */
  797.          update_window(0);
  798.       }
  799.  
  800.       /* restore windows if we did a temp switch above */
  801.  
  802.       if (cur_isnt_top) {
  803.          wincpy(winlis,&cw);
  804.          savefiles(cw.save_files,cw.nfiles);
  805.          wincpy(&cw,curwin);
  806.          restorefiles(cw.save_files,cw.nfiles);
  807.       }
  808.    }
  809. }
  810.  
  811.  
  812. /*****************************************************************************
  813.                       D I S P _ E M P T Y _ M S G
  814.  *****************************************************************************/
  815.  
  816. static int ALTCALL
  817. disp_empty_msg(on)     /* display empty dir msg w/wo highlighting */
  818. int on;
  819. {
  820.    if (on)
  821.       setvattrib(DIS_HIGH);
  822.  
  823.    disp_str_at("No files!",cw.fnrow+1,SCREEN_COLS/2-5);
  824.  
  825.    if (on)
  826.       setvattrib(DIS_NORM);
  827. }
  828.  
  829.  
  830. /*****************************************************************************
  831.                         D I S P _ D I R N A M E
  832.  *****************************************************************************/
  833.  
  834. disp_dirname() {       /* display the dir name header */
  835.  
  836.    char allmsg[20];
  837.  
  838.    if (cw.showall) {                   /* special header if showall mode */
  839.  
  840.       strcpy(allmsg,"FILES ON DRIVE ");
  841.       strncat(allmsg,cw.dirbuf,2);
  842.       center_text(cw.fwrow,allmsg);
  843.  
  844.    } else
  845.  
  846.       center_text(cw.fwrow,cw.dirbuf);    /* disp the dir name */
  847. }
  848.  
  849.  
  850. /*****************************************************************************
  851.                           I N F O H E A D
  852.  *****************************************************************************/
  853.  
  854. infohead() {           /* display the info header */
  855.  
  856.    setvattrib(DIS_HEAD);
  857.    disp_str_at("      NAME           USED  ALLOCATED     DATE         TIME      R H S A DIR",
  858.       FIRST_NROW,0);
  859.    clr_eol();
  860.    setvattrib(DIS_NORM);
  861. }
  862.  
  863.  
  864. /*****************************************************************************
  865.                             S H O W _ A L L
  866.  *****************************************************************************/
  867.  
  868. show_all() {
  869.  
  870.    if (anyshowall && !cw.showall)      /* only one window can do showall */
  871.       show_error(0,ONE_SH_ALL,1,"Only one window can show all files!");
  872.  
  873.    if (cw.showall ^= 1) {      /* toggle showall mode */
  874.  
  875.       /* showall mode is being turned on, allocate space for dir name ptrs */
  876.  
  877.       if ((dirlst = (char **) calloc(MAX_DIR,sizeof(char *))) == NULL) {
  878.          cw.showall = 0;
  879.          show_error(0,NO_MEM,1,"Out of memory!  Show All is not active!");
  880.       }
  881.  
  882.       if (numwin == 1) {       /* make row for showall header if not already */
  883.          cw.fnrow++;
  884.          cw.ndrows--;
  885.       }
  886.  
  887.       anyshowall = TRUE;       /* yes, a window has showall turned on */
  888.  
  889.    } else              /* showall is being turned off */
  890.  
  891.       showoff();
  892.  
  893.    renew_window();     /* redo window with/without showall mode */
  894. }
  895.  
  896. /*****************************************************************************
  897.                               S H O W O F F
  898.  *****************************************************************************/
  899.  
  900. showoff() {            /* turn off show all mode */
  901.  
  902.    register int i;
  903.    register char **cp;
  904.  
  905.    for (i = 0, cp = dirlst; i < diridx; i++, cp++)     /* release dir name */
  906.        free(*cp);                                      /*   memory */
  907.  
  908.    free((char *)dirlst);       /* now release pointer memory */
  909.  
  910.    diridx = 0;                 /* reset for next time */
  911.    dirlst = NULL;
  912.  
  913.    cw.showall = anyshowall = FALSE;    /* no window has showall now */
  914.  
  915.    if (numwin == 1) {          /* release showall header line if not needed */
  916.       cw.fnrow--;
  917.       cw.ndrows++;
  918.    }
  919. }
  920.  
  921.  
  922. /******************************************************************************
  923.                               W I N C P Y
  924.  ******************************************************************************/
  925.  
  926. static int ALTCALL
  927. wincpy(to,from)        /* copy window structures - I made this a separate */
  928. WINDOW *to, *from;     /* routine cause MSC generates a bunch of code for */
  929. {                      /* each structure asignment - in reality, it just a */
  930.                        /* little more than the code required to call this */
  931.                        /* function, but... */
  932.  
  933.    *to = *from;        /* not much to look at */
  934. }
  935.  
  936.  
  937. /******************************************************************************
  938.  **                  S A V E / R E S T O R E  F I L E S                      **
  939.  ******************************************************************************/
  940.  
  941. static int ALTCALL
  942. savefiles(fp,nf)       /* copy files[] to save area */
  943. char far *fp;
  944. int nf;
  945. {
  946.    movedata(dataseg,(unsigned int) files,FP_SEG(fp),FP_OFF(fp),
  947.              nf * sizeof(FILE_ENT));
  948. }
  949.  
  950. static int ALTCALL
  951. restorefiles(fp,nf)    /* copy files[] from save area */
  952. char far *fp;
  953. int nf;
  954. {
  955.    movedata(FP_SEG(fp),FP_OFF(fp),dataseg,(unsigned int) files,
  956.             nf * sizeof(FILE_ENT));
  957. }
  958.